//////////////////////////////////////////////////////////////////////////
/*
	Class for Managing RIR (Regional IP Registry)

														Written by novice.		
														Feb. 11th. 2006.
	e-mail : novice@joymax.com
*/
//////////////////////////////////////////////////////////////////////////


#pragma once

//////////////////////////////////////////////////////////////////////////
// Some Definitions...
#define FILE_BUFFER_SIZE	4096
//////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////
// Utility Macro.
#define TRUNCATE_IP( __x, __bit ) ( (__x << __bit) >> __bit )
#define REVERSE_IP( __x ) (DWORD)((DWORD)((BYTE)(__x>>0)<<24) | (DWORD)((BYTE)(__x>>8)<<16) | (DWORD)((BYTE)(__x>>16)<<8) | (DWORD)((BYTE)(__x>>24)<<0))
//////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////
// Statistics Information Structure.
#pragma pack (push, 1)
typedef struct _IPInfoRow
{
	TCHAR	szCode[4];
	DWORD	dwStartIP;
	DWORD	dwValue;
} IPINFOROW, *LPIPINFOROW;
#pragma pack (pop)
typedef std::map<DWORD, LPIPINFOROW>	IPINFO_MAP;



typedef struct _CountryCodeMapper
{
	TCHAR	szCode[2];
	TCHAR	szCountryName[64];
} COUNTRY_CODE_MAPPER, *LPCOUNTRY_CODE_MAPPER;
typedef std::map<std::string, std::string>	COUNTRY_CODE_MAP;

enum eHeaderClass
{
	eASN	= 0,
	eIPV4	= 1,
	eIPV6	= 2,
	eHeaderCount
};
typedef std::vector<std::string>	PARSE_SEQUENCE;
//////////////////////////////////////////////////////////////////////////

class CIPStatisticsMngr
{
public:
	static CIPStatisticsMngr* GetInstance()
	{
		if ( NULL == m_pThis )
			m_pThis = new CIPStatisticsMngr();

		return m_pThis;
	}

	static void Destroy()
	{
		if ( NULL != m_pThis )
			delete m_pThis;
	}

	void	Initialize();
	void	Finalize();

	BOOL	LoadCountryCode( LPCTSTR tszFileName );
	BOOL	LoadIPTables( LPCTSTR tszFileName );
	void	ReleaseResource();
	
	void	FindCountryOfIP( DWORD dwIP, OUT TCHAR* tszCode /*length : 8*/);
	void	GetCountryName( std::string strCountryCode, OUT std::string& strCountryName );
private:
	CIPStatisticsMngr()		{};
	~CIPStatisticsMngr()	{};

	static CIPStatisticsMngr* m_pThis;

	// Read and Process
	BOOL	ReadIPTableFile( LPCTSTR tszFileName );

	// Reading File Functions (Country Code Map)
	BOOL	OpenCountryCodeFile( LPCTSTR tszFileName );
	void	ParseCountryInfo( IN LPCTSTR lptszLineContext );

	// Reading File Functions (IPTable)
	BOOL	OpenIPTableFile( LPCTSTR tszFileName );
	BOOL	ReadFile( OUT HANDLE& hFile, IN LPCTSTR tszFileName, OUT LPVOID& pBuffer, OUT LARGE_INTEGER& llFileSize );

	// Processing for IP MAP
	TCHAR*	ReadLine( BOOL bSkip = FALSE, int nLeastLength = 0 );
	void	ParseHeaderInfo();
	void	AssignHeaderInfo( IN OUT IPINFOROW& sIPInfo );
	void	ParseIPRowInfo( IN LPCTSTR lptszLineContext, OUT LPIPINFOROW lpIPInfo );

	// Finding Function
	BOOL	SearchCountryOfIPRange( DWORD dwIPRange, DWORD dwIP, OUT TCHAR* tszCode /*length : 8*/);

	// Utility Functions
public:
	void	GenerateIP( LPCTSTR lptszIP, OUT DWORD& dwIP );
protected:
	BOOL	IsSearchable( DWORD dwValue );

	LPVOID				m_pTempContextForIP;			// Context for Reading File
	LPVOID				m_pTempContextForCountryCode;	// Context for Reading File
	char*				m_pCurPos;						// Read Point
	char				m_szTempLineContext[4096];		// Temporary Line Parsing Buffer
	HANDLE				m_hIPFile;						// RIR Flle Handle
	HANDLE				m_hCountryCodeFile;				// RIR Flle Handle
	LARGE_INTEGER		m_llRIRFileSize;				// RIR File Size
	LARGE_INTEGER		m_llCountryCodeFileSize;		// Country Code File Size

	int					m_nASNCount;
	int					m_nIPV4Count;
	int					m_nIPV6Count;

	IPINFO_MAP			m_IPInfoMap;
	COUNTRY_CODE_MAP	m_CountryCodeMap;
	PARSE_SEQUENCE		m_vecParseSequence;
};

#define IPSTATISTICS_MGR	CIPStatisticsMngr::GetInstance()